#include "agency_event_service.h"
#include "context.h"
#include "streamdata.h"
#include "log.h"
#include "agencyeventmgr.h"


static bool __init__ = AgencyEventService::Instance()->Init();

bool AgencyEventService::Init()
{
    Ctx.msg_router.BindMsg(agency_event_proto::AGENCY_EVENT_CMD_GET_RESP, std::bind(&AgencyEventService::OnAgencyEventGet, this, std::placeholders::_1));
    Ctx.msg_router.BindMsg(agency_event_proto::AGENCY_EVENT_CMD_GET_AGENCYID_RESP, std::bind(&AgencyEventService::OnGetAgencyId, this, std::placeholders::_1));
    return true;
}

bool AgencyEventService::HandleGetAgencyEvent(const std::uint32_t& agencyid, std::string&& trans, std::uint64_t sence)
{
    log_debug("agencyid:%u,sence:%llu", agencyid, sence);
    StreamData stream_data;
    StreamDataWriter write(stream_data);
    write.Write<std::uint64_t>(sence);
    write.WriteString(trans);

    agency_event_proto::GetReq agency_get_req;
    agency_get_req.set_id(agencyid);
    agency_get_req.set_trans(std::move(stream_data.Data()));
    Ctx.host->MtSendtoSrv(agency_event_proto::AGENCY_EVENT_CMD_GET_REQ, SERVER_TYPE_AGENCY_EVENT, &agency_get_req, 0);
    return true;
}

bool AgencyEventService::HandleGetAgencyId(const std::string& agency_name, std::string&& trans, std::uint64_t sence)
{
    log_debug("agency_name:%s, sence:%llu", agency_name.c_str(), sence);
    StreamData stream_data;
    StreamDataWriter write(stream_data);
    write.Write<std::uint64_t>(sence);
    write.WriteString(trans);

    agency_event_proto::GetAgencyIdReq agency_req;
    agency_req.set_agency_name(agency_name);
    agency_req.set_trans(std::move(stream_data.Data()));
    Ctx.host->MtSendtoSrv(agency_event_proto::AGENCY_EVENT_CMD_GET_AGENCYID_REQ, SERVER_TYPE_AGENCY_EVENT, &agency_req, 0);
    return true;
}

void AgencyEventService::OnAgencyEventGet(MsgData&& data)
{
    do
    {
        agency_event_proto::GetResp agencyevent_get_resp;
        if (!agencyevent_get_resp.ParseFromArray(data.data.c_str(), data.data.size()))
        {
            log_error("parser agency_event_proto::GetResp failed, stype:%d,svid:%d,uuid:%d", data.svtype, data.svid, data.uuid);
            break;
        }

        StreamData stream_data(std::move(*agencyevent_get_resp.mutable_trans()));
        StreamDataReader reader(stream_data);
        std::uint64_t sence = reader.Read<std::uint64_t>();
        std::string trans = reader.ReadString();

        log_debug("sence:%llu,resp:%s", sence, agencyevent_get_resp.ShortDebugString().c_str());
        try
        {
            if (agencyevent_get_resp.err_code() == 0)
            {
                stAgencyEvent agencyevent;
                agencyevent.CopyFrom(agencyevent_get_resp.agencyevent());
                AgencyEventMgr::Instance()->Update(std::move(agencyevent));

                stAgencyEvent* p_agencyevent = AgencyEventMgr::Instance()->Get(agencyevent_get_resp.agencyevent().agency_id());
                OnSenceAgencyEventGet(sence, std::move(trans), agencyevent_get_resp.err_code(), p_agencyevent);
            }
            else
            {
                OnSenceAgencyEventGet(sence, std::move(trans), agencyevent_get_resp.err_code(), nullptr);
            }
        }
        catch(const std::exception& e)
        {
            log_error("catch exception:%s, sence:%d, stype:%d,svid:%d,uuid:%d,msg:%s", e.what(), sence, data.svtype, data.svid, data.uuid, agencyevent_get_resp.ShortDebugString().c_str());
        }
        catch(...)
        {
            log_error("catch unknown exception, sence:%d, stype:%d,svid:%d,uuid:%d,msg:%s", sence, data.svtype, data.svid, data.uuid, agencyevent_get_resp.ShortDebugString().c_str());
        }
    } while(false);
}

void AgencyEventService::OnSenceAgencyEventGet(std::uint64_t sence, std::string&& trans, std::int32_t err_code, stAgencyEvent* agencyevent)
{
    auto it = m_agencyevent_get_listen.find(sence);
    if (it == m_agencyevent_get_listen.end())
    {
        log_warning("sence:%d not listen", sence);
        return;
    }
    it->second(err_code, agencyevent, std::move(trans));
}


void AgencyEventService::OnGetAgencyId(MsgData&& data)
{
    log_debug("OnGetAgencyId enter");
    do
    {
        agency_event_proto::GetAgencyIdResp agencyevent_get_resp;
        if (!agencyevent_get_resp.ParseFromArray(data.data.c_str(), data.data.size()))
        {
            log_error("parser agency_event_proto::GetAgencyIdResp failed, stype:%d,svid:%d,uuid:%d", data.svtype, data.svid, data.uuid);
            break;
        }

        StreamData stream_data(std::move(*agencyevent_get_resp.mutable_trans()));
        StreamDataReader reader(stream_data);
        std::uint64_t sence = reader.Read<std::uint64_t>();
        std::string trans = reader.ReadString();

        log_debug("sence:%llu, resp:%s", sence, agencyevent_get_resp.ShortDebugString().c_str());
        try
        {
            if (agencyevent_get_resp.err_code() == 0)
            {
                stAgencyEvent agencyevent;
                agencyevent.CopyFrom(agencyevent_get_resp.agencyevent());
                AgencyEventMgr::Instance()->Update(std::move(agencyevent));

                stAgencyEvent* p_agencyevent = AgencyEventMgr::Instance()->GetAgencyId(agencyevent_get_resp.agencyevent().agency_name());
                OnSenceAgencyEventGet(sence, std::move(trans), agencyevent_get_resp.err_code(), p_agencyevent);
            }
            else
            {
                OnSenceAgencyEventGet(sence, std::move(trans), agencyevent_get_resp.err_code(), nullptr);
            }
        }
        catch(const std::exception& e)
        {
            log_error("catch exception:%s, sence:%d, stype:%d,svid:%d,uuid:%d,msg:%s", e.what(), sence, data.svtype, data.svid, data.uuid, agencyevent_get_resp.ShortDebugString().c_str());
        }
        catch(...)
        {
            log_error("catch unknown exception, sence:%d, stype:%d,svid:%d,uuid:%d,msg:%s", sence, data.svtype, data.svid, data.uuid, agencyevent_get_resp.ShortDebugString().c_str());
        }
    } while(false);
}
